package com.xiaoyu.lanling.data;

import android.content.Context;
import android.content.res.Configuration;
import android.text.TextUtils;

import com.xiaoyu.base.app.AppContext;
import com.xiaoyu.base.config.HttpConfig;
import com.xiaoyu.base.data.CacheData;
import com.xiaoyu.base.data.DocData;
import com.xiaoyu.base.data.UserData;
import com.xiaoyu.base.utils.ListUtil;
import com.xiaoyu.base.utils.MMKVUtil;
import com.xiaoyu.lanling.BuildConfig;
import com.xiaoyu.lanling.common.Constant;
import com.xiaoyu.lanling.router.deeplink.DeepLinkRouter;
import com.xiaoyu.net.request.RequestWithJsonDataReturn;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import in.srain.cube.app.init.InitializableAsync;
import in.srain.cube.cache.DiskCacheProvider;
import in.srain.cube.cache.DiskFileUtils;
import in.srain.cube.request.FailData;
import in.srain.cube.request.JsonData;
import in.srain.cube.request.RequestDefaultHandler;
import in.srain.cube.util.CLog;

public class ConfigData implements InitializableAsync {

    private static final String TAG = "ConfigData";

    private static final String CONFIG_CACHE_KEY = "app-config";
    private static final String LANGUAGE_EN = "en";
    private static final String LANGUAGE_ZH = "zh";

    private static final String GENESIS_CONFIG_KEY = "genesisConfig";

    private static ConfigData sInstance;
    private String mLanguage = LANGUAGE_ZH;
    private boolean mIsGlobalRequesting = false;
    private boolean mIsGenesisRequesting = false;
    private ConfigInfo mConfigInfo = ConfigInfo.EMPTY;

    private ConfigData() {
        mLanguage = Locale.getDefault().getLanguage();
    }

    public static synchronized ConfigData getInstance() {
        if (sInstance == null) {
            sInstance = new ConfigData();
        }
        return sInstance;
    }

    public void forceRequestGlobalConfig() {
        // tryToRequestGlobalConfig(0, true);
    }

    public void tryToRequestGlobalConfig(int version) {
        // tryToRequestGlobalConfig(version, false);
    }

    public void tryToRequestGlobalConfig(int version, boolean force) {
        if (mIsGlobalRequesting) {
            return;
        }
        mIsGlobalRequesting = true;

        final RequestWithJsonDataReturn<JsonData> request = new RequestWithJsonDataReturn<>();
        request.setRequestHandler(new RequestDefaultHandler<JsonData, JsonData>() {
            @Override
            public JsonData processOriginData(JsonData originData) {
                JsonData data = originData.optJson("data");
                updateGlobalConfig(data);
                return originData;
            }

            @Override
            public void onRequestFinish(JsonData data) {
                mIsGlobalRequesting = false;
                MMKVUtil.get().putString(Constant.MMKVKey.KEY_GLOBAL_CONFIG_LAST_VERSION_NAME, BuildConfig.VERSION_NAME).apply();
            }

            @Override
            public void onRequestFail(FailData failData) {
                super.onRequestFail(failData);
                mIsGlobalRequesting = false;
            }
        });

        // String globalConfigUrl = String.format("%s/%s/%s", HttpConfig.BASE_GLOBAL_CONFIG, AppConfig.appKey(), version);
        // if (force) {
        //     globalConfigUrl = String.format("%s/%s/10000/%s", HttpConfig.BASE_GLOBAL_CONFIG, AppConfig.appKey(), System.currentTimeMillis());
        // }
        // final RequestData requestData = request.getRequestData();
        // requestData.setRequestUrl(globalConfigUrl);
        // request.enqueue();
    }

    public void tryRequestGenesisConfig() {
        if (mIsGenesisRequesting) {
            return;
        }
        mIsGenesisRequesting = true;

        final RequestWithJsonDataReturn<JsonData> request = new RequestWithJsonDataReturn<>();
        request.setRequestHandler(new RequestDefaultHandler<JsonData, JsonData>() {
            @Override
            public JsonData processOriginData(JsonData originData) {
                JsonData data = originData.optJson("data");
                updateGenesisConfig(data);
                return originData;
            }

            @Override
            public void onRequestFinish(JsonData data) {
                mIsGenesisRequesting = false;
                MMKVUtil.get().putString(Constant.MMKVKey.KEY_GLOBAL_CONFIG_LAST_VERSION_NAME, BuildConfig.VERSION_NAME).apply();
            }

            @Override
            public void onRequestFail(FailData failData) {
                super.onRequestFail(failData);
                mIsGenesisRequesting = false;
            }
        });

        String uid = UserData.getInstance().getUid();
        if (TextUtils.isEmpty(uid)) {
            uid = "0";
        }
        final long timestamp = System.currentTimeMillis();
        final int random = new Random().nextInt(100);

        // String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        // final String genesisConfigUrl = String.format("%s/%s/%s/%s/%s %s", HttpConfig.BASE_GENESIS_CONFIG, AppConfig.appKey(), date, uid, timestamp, random);
        // final RequestData requestData = request.getRequestData();
        // requestData.setRequestUrl(genesisConfigUrl);
        // request.enqueue();
    }

    public void processGlobalVersionCode(int version) {
        CLog.d(TAG, "processGlobalVersionCode: %s %s", version, mConfigInfo.version);

        final String lastVersionName = MMKVUtil.get().getString(Constant.MMKVKey.KEY_GLOBAL_CONFIG_LAST_VERSION_NAME, "");

        if (version > mConfigInfo.version || !TextUtils.equals(lastVersionName, BuildConfig.VERSION_NAME)) {
            tryToRequestGlobalConfig(version);
        }
    }

    private synchronized void updateGenesisConfig(JsonData genesisJsonData) {
        if (genesisJsonData.optJson("genesis").optJson("api_hosts").asList().isEmpty()) {
            return;
        }
        mConfigInfo.rawJson.put(GENESIS_CONFIG_KEY, genesisJsonData);
        saveConfigToLocal();
        processGenesisConfigData();
    }

    private synchronized void updateGlobalConfig(JsonData globalJsonData) {
        JsonData genesisJsonData = mConfigInfo.rawJson.optJson(GENESIS_CONFIG_KEY);
        globalJsonData.put(GENESIS_CONFIG_KEY, genesisJsonData);

        replaceConfig(new ConfigInfo(globalJsonData));
        saveConfigToLocal();
        processGlobalConfigData(true);
    }

    private synchronized void replaceConfig(ConfigInfo configInfo) {
        mConfigInfo = configInfo;
    }

    public synchronized void onConfigurationChanged(Configuration newConfig) {
        mLanguage = newConfig.locale.getLanguage();
        processGlobalConfigData(false);
    }

    public String getLanguage() {
        return mLanguage;
    }

    public boolean isLanguageZH() {
        return mLanguage.equals(LANGUAGE_ZH);
    }

    private void processGlobalConfigData(boolean forceDownload) {
        CLog.i(TAG, "processGlobalConfigData: %s", mConfigInfo.version);
        String languageKey = LANGUAGE_ZH;
        if (TextUtils.isEmpty(mLanguage) || !mLanguage.equals(LANGUAGE_ZH)) {
            languageKey = LANGUAGE_EN;
        }

        JsonData jsonData = mConfigInfo.rawJson;
        DocData.getInstance().updateDocList(jsonData.optJson("docList").optJson(languageKey));
        DeepLinkRouter.getInstance().updateForRouterConfig(jsonData.optJson("routeList"));

        if (jsonData.has("lottieConfig")) {
            this.prepareLottie(jsonData.optJson("lottieConfig"), forceDownload);
        }

        if (jsonData.has("svgaConfig")) {
            this.prepareSvga(jsonData.optJson("svgaConfig"), forceDownload);
        }
    }

    private void prepareLottie(JsonData jsonData, boolean force) {
        // LottieData.getInstance().prepareLottie(jsonData);
        // LottieData.getInstance().downloadLottieJsonFile(force);
    }

    private void prepareSvga(JsonData jsonData, boolean force) {
        // SvgaData.getInstance().prepareSvga(jsonData);
        // SvgaData.getInstance().downloadSvgaJsonFile(force);
    }

    private void processGenesisConfigData() {
        JsonData genesisJsonData = mConfigInfo.rawJson.optJson(GENESIS_CONFIG_KEY);
        CLog.d(TAG, "processGenesisConfigData: %s", genesisJsonData);
        List<String> apiHosts = genesisJsonData.optJson("genesis").optJson("api_hosts").asList();
        String apiHost = ListUtil.getRandom(apiHosts, "");
        if (!TextUtils.isEmpty(apiHost)) {
            HttpConfig.setHost(apiHost);
            CLog.i(TAG, "setHost: %s", apiHost);
        }
    }

    @Override
    public void initiateAsync(Context context) {
        loadConfigFromLocal();
        tryRequestGenesisConfig();
    }

    private void saveConfigToLocal() {
        final DiskCacheProvider diskCacheProvider = CacheData.getInstance().getDiskCacheProvider();
        if (diskCacheProvider != null) {
            diskCacheProvider.write(CONFIG_CACHE_KEY, mConfigInfo.rawJson.toString());
            diskCacheProvider.flushDiskCacheAsync();
        }
    }

    public void loadConfigFromLocal() {
        // final ConfigInfo cacheConfig = loadConfigFromCache();
        final ConfigInfo initConfig = loadInitConfigFromAssets();
        // final ConfigInfo configInfo = cacheConfig.version > initConfig.version ? cacheConfig : initConfig;
        final ConfigInfo configInfo = initConfig;
        replaceConfig(configInfo);
        processGenesisConfigData();
        processGlobalConfigData(false);
    }

    private ConfigInfo loadInitConfigFromAssets() {
        final String assertInitDataPath = "init/config.json";
        final String jsonDataStr = DiskFileUtils.readAssert(AppContext.getContext(), assertInitDataPath);
        return new ConfigInfo(JsonData.create(jsonDataStr));
    }

    private ConfigInfo loadConfigFromCache() {
        final DiskCacheProvider diskCacheProvider = CacheData.getInstance().getDiskCacheProvider();
        String cacheDataStr = diskCacheProvider.read(CONFIG_CACHE_KEY);
        return new ConfigInfo(JsonData.create(cacheDataStr));
    }

    private JsonData getJsonDataFromKey(String key) {
        return mConfigInfo.rawJson.optJson(key);
    }

    public JsonData getJsonData() {
        return mConfigInfo.rawJson;
    }

    public int getVersion() {
        return mConfigInfo.version;
    }

    public JsonData getUrlListJsonData() {
        return getJsonDataFromKey("urlList");
    }

    public JsonData getSvgaConfig() {
        return getJsonDataFromKey("svgaConfig");
    }

    public String getSvgaNormalGift(String key) {
        return getSvgaConfig().optJson("normalGift").optString(key);
    }

    public String getUrl(String key) {
        return getUrlListJsonData().optString(key);
    }

    private static class ConfigInfo {
        static ConfigInfo EMPTY = new ConfigInfo(JsonData.create(new HashMap<>(0)));
        private final int version;
        private final JsonData rawJson;

        public ConfigInfo(JsonData jsonData) {
            version = jsonData.optInt("version");
            rawJson = jsonData;
        }
    }
}
